#pragma once
#include"Common.hpp"
#include"Channel.hpp"

class EventLoop;
using Run_cb = std::function<void()>;
using Release_cb = std::function<void()>;
class TimerTask
{
private:
    // 任务id
    uint64_t _id;
    bool _iscancel;
    // 超时时间
    int _timeout;
    // 运行任务
    Run_cb _run_task;
    // 取消任务
    Release_cb _release_task;

public:
    TimerTask(uint64_t id, int timeout) : _id(id), _iscancel(false), _timeout(timeout)
    {
    }
    void SetRunTaskCallBack(const Run_cb &run_cb)
    {
        _run_task = run_cb;
    }
    void SetReleaseCallBack(const Release_cb &release_cb)
    {
        _release_task = release_cb;
    }
    void CancelEnable(bool flag)
    {
        _iscancel = flag;
    }
    ~TimerTask()
    {

        //修改bug
        //1.先判断任务是否取消！
        if (!_iscancel && _run_task)
        {
            _run_task();
        }
        if (_release_task)
        {
            _release_task();
        }
    }
    uint64_t Id()
    {
        return _id;
    }
    int Timeout()
    {
        return _timeout;
    }
};

#define MAX_TIMEOUT 60
class TimerWheel
{
public:
    using WeakPtr = std::weak_ptr<TimerTask>; // 解决循环引用问题
    using TaskrPtr = std::shared_ptr<TimerTask>;
    using Bucket = std::vector<TaskrPtr>;
    using BucketList = std::vector<Bucket>;

private:
    // 时间轮对象
    BucketList _timerWheel;
    EventLoop *_loop;
    // 为时间轮分配的channel管理事件
    std::unique_ptr<Channel> _channel_timer;
    // 秒针
    int _click;
    // 刻度
    int _capacity;
    int _timerfd;
    // 任务映射表
    std::unordered_map<uint64_t, WeakPtr> _timerTask_map;

private:
    static int CreateTimerfd()
    {
        int timerfd = ::timerfd_create(CLOCK_MONOTONIC, 0);
        if (timerfd < 0)
        {
            LOG(FATAL, "创建定时器异常\n");
            abort();
        }
        struct itimerspec new_settimer;
        new_settimer.it_interval.tv_sec = 1;
        new_settimer.it_interval.tv_nsec = 0;
        // 设置第一次超时时间
        new_settimer.it_value.tv_sec = 1;
        new_settimer.it_value.tv_nsec = 0;
        int ret = timerfd_settime(timerfd, 0, &new_settimer, nullptr);
        if (ret < 0)
        {
            LOG(ERROR, "设置超时时间异常!\n");
            abort();
        }
        LOG(DEBUG, "初始化定时器完毕!\n");
        return timerfd;
    }
    uint64_t GetTimeoutCounts()
    {
        uint64_t val = 0;
        // sleep(3);测试超时次数
        ssize_t n = ::read(_timerfd, &val, sizeof(val));
        if (n < 0)
        {
            LOG(ERROR, "获取超时次数异常!\n");
            abort();
        }
        LOG(DEBUG, "读取定时器完毕!,超时次数:%d\n", val);
        return val;
    }

public:
    TimerWheel(EventLoop *loop, int max_time_scale = MAX_TIMEOUT)
        : _timerWheel(max_time_scale),
          _loop(loop),
          _click(0),
          _capacity(max_time_scale)
    {
        _timerfd = CreateTimerfd();
        // 为时间轮分配一个Channel，监控其的读事件
        _channel_timer = std::make_unique<Channel>(_loop, _timerfd);

        // 启动读事件监控
        _channel_timer->SetReadCallback(std::bind(&TimerWheel::Start, this));
        _channel_timer->OpenReadEventMonitoring();
    }
    ~TimerWheel()
    {
    }
    bool HasTask(uint64_t id)
    {
        auto iter = _timerTask_map.find(id);
        if (iter == _timerTask_map.end())
        {
            return false;
        }
        return true;
    }
    // 在一个loop循环中处理添加任务
    void AddTaskToTimerWheelInLoop(const Run_cb &run_cb, int timeout, uint64_t id);
    // 刷新/延迟定时任务
    void RefreshTaskInLoop(uint64_t id);
    // 取消任务
    void CancelTaskInLoop(uint64_t id);

private:
    // 执行超时任务
    void Start()
    {
        int counts = GetTimeoutCounts();
        for (int i = 0; i < counts; i++)
        {
            RunTimerWheel();
        }
    }
    // 添加任务
    void TimerTaskAdd(const Run_cb &run_cb, int timeout, uint64_t id)
    {
        if (timeout > 60 || timeout <= 0)
        {
            LOG(ERROR, "超时时间允许范围[1,60],你的timeout为: %d\n", timeout);
            return;
        }
        TaskrPtr newobj = std::make_shared<TimerTask>(id, timeout);
        newobj->SetRunTaskCallBack(run_cb);
        newobj->SetReleaseCallBack(std::bind(&TimerWheel::RemoveTask, this, id));
        // 添加进映射表
        _timerTask_map[id] = WeakPtr(newobj);
        // 设置秒针位置
        _timerWheel[(_click + timeout) % _capacity].push_back(newobj);
    }
    // 删除任务
    void RemoveTask(uint64_t id)
    {
        auto iter = _timerTask_map.find(id);
        if (iter != _timerTask_map.end())
        {
            _timerTask_map.erase(iter);
        }
    }
    // 刷新任务
    void RefreshTimeTask(uint64_t id)
    {
        auto iter = _timerTask_map.find(id);
        // assert(iter != _timerTask_map.end());//修改
        if(iter == _timerTask_map.end()) return;
        TaskrPtr obj =  iter->second.lock();
        int timeout = obj->Timeout();
        _timerWheel[(_click + timeout) % _capacity].push_back(TaskrPtr(iter->second));
    }
    // 运行时间轮
    void RunTimerWheel()
    {
        _click = (_click + 1) % _capacity;
        _timerWheel[_click].clear();
    }
    // 取消任务
    void CancelTask(uint64_t id)
    {
        auto iter = _timerTask_map.find(id);
        if (iter == _timerTask_map.end())
        {
             return;
        }
        TaskrPtr objptr = iter->second.lock();
        if (objptr) 
        {
            objptr->CancelEnable(true);
        }
            
    }
};